package com.zxy.ziems.server.statistics.service.impl;

import com.zxy.ziems.server.classify.pojo.entity.ClassifyDeviceProperty;
import com.zxy.ziems.server.classify.pojo.vo.ClassifyTreeNode;
import com.zxy.ziems.server.classify.service.ClassifyDevicePropertyService;
import com.zxy.ziems.server.classify.service.ClassifyService;
import com.zxy.ziems.server.constant.DateType;
import com.zxy.ziems.server.constant.enums.DictCodeEnum;
import com.zxy.ziems.server.domain.DictItem;
import com.zxy.ziems.server.dto.DataQueryDto;
import com.zxy.ziems.server.energy.service.DataChartService;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.service.DictService;
import com.zxy.ziems.server.statistics.converter.CacheDataConverter;
import com.zxy.ziems.server.statistics.pojo.entity.CacheData;
import com.zxy.ziems.server.statistics.pojo.vo.EnergyFlowTreeVO;
import com.zxy.ziems.server.statistics.service.CacheDataService;
import com.zxy.ziems.server.statistics.service.EnergyFlowService;
import com.zxy.ziems.server.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class EnergyFlowServiceImpl implements EnergyFlowService {

    private static final Logger log = LoggerFactory.getLogger(EnergyFlowServiceImpl.class);
    @Autowired
    private ClassifyService classifyService;

    @Autowired
    private DataChartService dataChartService;

    @Autowired
    private ClassifyDevicePropertyService classifyDevicePropertyService;

    @Autowired
    private CacheDataService cacheDataService;

    @Autowired
    private CacheDataConverter converter;

    @Autowired
    private DictItemService dictItemService;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    @Transactional
    public EnergyFlowTreeVO tree(DataQueryDto dataQueryDto) {

        String index = dataQueryDto.getClassifyId() + ":" + dataQueryDto.getStartDay();
        CacheData cacheData = cacheDataService.getByTypeAndIndex(dataQueryDto.getQueryType(), index);

        if (cacheData != null) {

            EnergyFlowTreeVO energyFlowTreeVO = converter.convertToJsonObject(cacheData.getContent(), EnergyFlowTreeVO.class);
            return energyFlowTreeVO;

        }
        // 查看能流图树
        List<ClassifyTreeNode> classifyTreeNodes = classifyService.treeByParentClassifyId(null, null, dataQueryDto.getClassifyId());

        // 最上级只有一个
        ClassifyTreeNode classifyTreeNode = classifyTreeNodes.get(0);

        // 计算用量和百分比
        EnergyFlowTreeVO result = new EnergyFlowTreeVO();
        copyProperty(classifyTreeNode, result);

        // 获取总用电
        dataQueryDto.setClassifyId(result.getClassifyId());
        // 获取当前分类下，所有点位合计
        Map<String, BigDecimal> curClassifySum = dataChartService.getCurClassifySum(dataQueryDto);
        result.setRatio(BigDecimal.ONE);
        BigDecimal allTotal = curClassifySum.get(result.getClassifyId());
        result.setTotal(allTotal);
        // 计算
        List<EnergyFlowTreeVO> calculate = calculate(classifyTreeNode.getChildren(), allTotal, dataQueryDto);
        result.setChildren(calculate);

        cacheDataService.save(dataQueryDto.getQueryType(), index, result);

        return result;
    }

    private static void copyProperty(ClassifyTreeNode classifyTreeNode, EnergyFlowTreeVO result) {
        result.setClassifyId(classifyTreeNode.getClassifyId());
        result.setClassifyName(classifyTreeNode.getClassifyName());
        result.setSort(classifyTreeNode.getSort());
        result.setTreeId(classifyTreeNode.getTreeId());
        result.setParentClassifyId(classifyTreeNode.getParentClassifyId());
    }

    private List<EnergyFlowTreeVO> calculate(List<ClassifyTreeNode> list, BigDecimal total, DataQueryDto dataQueryDto) {
        List<EnergyFlowTreeVO> energyFlowTreeVOS = new ArrayList<>();
        if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
            return energyFlowTreeVOS;
        }
        for (ClassifyTreeNode classifyTreeNode : list) {
            EnergyFlowTreeVO energyFlowTreeVO = new EnergyFlowTreeVO();
            copyProperty(classifyTreeNode, energyFlowTreeVO);
            energyFlowTreeVOS.add(energyFlowTreeVO);
            // 当前分类下是否有点位，如果有计算当前分类下点位和，没有则从子集和相加
            List<ClassifyDeviceProperty> classifyDeviceProperties = classifyDevicePropertyService.getByClassId(classifyTreeNode.getClassifyId());

            if (!CollectionUtils.isEmpty(classifyDeviceProperties)) {
                dataQueryDto.setClassifyId(classifyTreeNode.getClassifyId());
                Map<String, BigDecimal> curClassifySum = dataChartService.getCurClassifySum(dataQueryDto);
                //
                BigDecimal total1 = curClassifySum.get(classifyTreeNode.getClassifyId());
                log.info("classifyId："+classifyTreeNode.getClassifyId());
                energyFlowTreeVO.setTotal(total1);
                energyFlowTreeVO.setRatio(total1.divide(total, 4, RoundingMode.HALF_UP));
            } else {
                // 获取子total
                List<EnergyFlowTreeVO> calculate = calculate(classifyTreeNode.getChildren(), total, dataQueryDto);
                BigDecimal reduce = calculate.stream().map(EnergyFlowTreeVO::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
                energyFlowTreeVO.setTotal(reduce);
                energyFlowTreeVO.setRatio(reduce.divide(total, 4, RoundingMode.HALF_UP));
            }

            if (!classifyTreeNode.getChildren().isEmpty()) {
                List<EnergyFlowTreeVO> calculate = calculate(classifyTreeNode.getChildren(), total, dataQueryDto);
                energyFlowTreeVO.setChildren(calculate);
            }
        }
        return energyFlowTreeVOS;
    }

    @Override
    public LocalDate syncDataDay(LocalDate date) {
        DataQueryDto dataQueryDto = new DataQueryDto();
        dataQueryDto.setStartDay(DateUtils.dateToString(date, DateUtils.YMD_PATTERN));
        dataQueryDto.setQueryType(DateType.CUR_DAY);

        List<DictItem> dictItems = dictItemService.getByDictCode(DictCodeEnum.ENERGY_FLOW.getCode());
        for (DictItem dictItem : dictItems) {
            dataQueryDto.setClassifyId(dictItem.getItemCode());
            tree(dataQueryDto);
        }
        return date.plusDays(1);
    }

    @Override
    public LocalDate syncDataMonth(LocalDate date) {
        DataQueryDto dataQueryDto = new DataQueryDto();
        dataQueryDto.setStartDay(DateUtils.dateToString(date, DateUtils.YM_PATTERN));
        dataQueryDto.setQueryType(DateType.CUR_MONTH);

        List<DictItem> dictItems = dictItemService.getByDictCode(DictCodeEnum.ENERGY_FLOW.getCode());
        for (DictItem dictItem : dictItems) {
            dataQueryDto.setClassifyId(dictItem.getItemCode());
            tree(dataQueryDto);
        }

        return date.plusMonths(1);
    }
}
